package com.kang.util;

import com.kang.dto.RecommendDto;
import com.kang.entity.Essay;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Recommend {

    private Map<Double, Integer> computeNearestNeighbor(RecommendDto recommendDto, List<RecommendDto> recommendDtoList) {
        Map<Double, Integer> distances =     new TreeMap<>();

        for (RecommendDto dto : recommendDtoList) {
            double distance = pearson_dis(dto.getMarkUserLikeEssayList(), recommendDto.getUserLikeEssayIdList());
            distances.put(distance, dto.getStatus());
        }


        return distances;
    }

    private double pearson_dis(List<Essay> a, List<Essay> b) {
        int n = a.size();
        List<Integer> rating1 = a.stream().map(Essay::getViewNum).collect(Collectors.toList());
        List<Integer> rating2 = b.stream().map(Essay::getViewNum).collect(Collectors.toList());


        double Ex = rating1.stream().mapToDouble(x -> x).sum();
        double Ey = rating2.stream().mapToDouble(y -> y).sum();
        double Ex2 = rating1.stream().mapToDouble(x -> Math.pow(x, 2)).sum();
        double Ey2 = rating2.stream().mapToDouble(y -> Math.pow(y, 2)).sum();
        double Exy = IntStream.range(0, n).mapToDouble(i -> rating1.get(i) * rating2.get(0)).sum();
        double numerator = Exy - Ex * Ey / n;
        double denominator = Math.sqrt((Ex2 - Math.pow(Ex, 2) / n) * (Ey2 - Math.pow(Ey, 2) / n));
        if (denominator == 0) return 0.0;
        return numerator / denominator;

    }

    public List<Integer> recommend(RecommendDto recommendDto, List<RecommendDto> recommendDtoList) {
        //找到最近邻 因为相似度越高代表越看过,越低就越火
        Map<Double, Integer> distances = computeNearestNeighbor(recommendDto, recommendDtoList);
        Integer nearest = distances.values().iterator().next();
        System.out.println("最近邻状态 -> " + nearest);

        List<RecommendDto> collect = recommendDtoList.stream().filter(v -> v.getStatus().equals(nearest)).collect(Collectors.toList());
        //获取最近用户喜欢的文章id
        List<Essay> markUserLikeEssayList = collect.get(0).getMarkUserLikeEssayList();
        List<Integer> resultList = new ArrayList<>();
        for (Essay essay : markUserLikeEssayList) {
            if (!recommendDto.getUserLikeEssayIdList().contains(essay)) {
                resultList.add(essay.getId());
            }
        }


        return resultList;
    }

}
